package com.acmedcare.framework.exchange.center.executer;

import java.util.Calendar;
import java.util.Date;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ProcessMonitor {

  private static ScheduledExecutorService executorService;

  //按照时间顺序入队,只对于时间超过当前时间的数据处理
  private static Queue<ProcessInfo> process;

  private static boolean started = false;

  private static void init() {

    log.info("任务监控器正在进行初始化!");
    if (process == null) {
      process = new ConcurrentLinkedDeque<>();
    }

    executorService = new ScheduledThreadPoolExecutor(2);
    executorService.scheduleAtFixedRate(() -> {

      String name = "";
      ProcessInfo processInfo = process.peek();
      while (processInfo != null) {
        try {

          name = processInfo.getTaskDetail().getName();
          if (processInfo.isStop() || !processInfo.getProcess().isAlive()) {
            process.remove();
            continue;
          }

          Calendar calendar = Calendar.getInstance();
          calendar.setTime(new Date());

          if (processInfo.getTime() <= 0) {
            processInfo.setTime(3);
          }

          // processInfo.setTime(0);
          calendar.add(Calendar.MINUTE, -processInfo.getTime());
          Date date = calendar.getTime();
          if (processInfo.getStartTime().before(date)) {

            //强制关闭
            processInfo.getTaskDetail().setExecuteLog("程序执行已经超过最大执行时间,已经被强制关闭!");
            processInfo.getProcess().destroyForcibly();
            process.remove();
          } else {

            //如果时间还在范围内则跳出循环，等待下一次进行扫描
            if (log.isDebugEnabled()) {

              log.debug("本次扫描结束,未找到过期任务,所有任务都在运行时间之内!");
            }
            return;
          }

        } catch (Exception ex) {

          log.info("任务进程处理异常,任务名称:" + name, ex);
        }finally {

          processInfo = process.peek();
        }
      }
    }, 1, 10, TimeUnit.SECONDS);

    started = true;
  }

  public static void addProcess(ProcessInfo processInfo) {

    if (started) {

      if (executorService.isShutdown() || executorService.isTerminated()) {
        log.warn("任务管理器发生意外关闭,正在进行重启!");
        init();
      }

      process.add(processInfo);
    } else {

      init();
      process.add(processInfo);
    }
  }
}
